package org.goodev.android.autowire;

import java.lang.reflect.Field;

import android.app.Activity;
import android.text.TextUtils;
import android.view.View;

/**
 * Autowire the {@link android.view.View} field from the layout xml file.
 * 
 * <p>User Guide</p>
 * <pre class="prettyprint">
 * public class MainActivity extends Activity {
 *     ...
 *
 *     @From private TextView mResultTv;
 *     @From("button") private Button btn;
 *     @From() private EditText uri;
 *     private URI getUri;
 *
 *     public void onCreate(Bundle savedInstanceState) {
 *     	super.onCreate(savedInstanceState);
 *     	setContentView(R.layout.main);
 *     	//Use following code to autowire the view
 *     	Wire.me(this, R.id.class);
 *     	//Don't need manually set field
 *       //result = (TextView) findViewById(R.id.result);
 *       //btn = (Button) findViewById(R.id.btn);
 *       //uri = (EditText) findViewById(R.id.url);
 *     	btn.setOnClickListener(new OnClickListener() {
 *     		public void onClick(View v) {
 *     			startTest();
 *     		}
 *     	});
 *     }
 * ...
 * </pre>
 * The layout xml :
 * <pre class="prettyprint">
 *  
 * &lt;EditText
 *    android:id="@+id/uri"
 *    android:layout_width="fill_parent" 
 *    android:layout_height="wrap_content"
 *    android:inputType="textUri" 
 *    /&gt;
    
&lt;Button  
 *    android:id="@+id/button"
 *    android:layout_width="fill_parent" 
 *    android:layout_height="wrap_content" 
 *    android:text="@string/test"
 *    /&gt;
&lt;TextView  
 *    android:id="@+id/resultTv"
 *    android:layout_width="fill_parent" 
 *    android:layout_height="wrap_content" 
 *    android:text="@string/hello"
 *   /&gt;
 * </pre>
 * 
 * <p>Recommend use the default name wire policy,</p>
 * <p>View filed name -> layout xml view id(uri -> uri)</p>
 * <p>or, </p>
 * <p>you can add  'm' before the field name(mResultTv -> resultTv)</p>
 * 
 * <p>you also can manually set the layout view id.(Such as the btn field)</p>
 *
 */
public class Wire {
	public static void me(Activity mActivity,Class<? extends Object> mId) {
		Field[] fields = mActivity.getClass().getDeclaredFields();
		for (int i = 0; i < fields.length; i++) {
			Field field = fields[i];
			if(field.isAnnotationPresent(From.class)) {
				String fieldName = field.getName();
				From from = field.getAnnotation(From.class);
				String userIdField = from.value();
				Field idField = null;
				System.out.println("userIdField = "+userIdField);
				if(!TextUtils.isEmpty(userIdField)) {
					try {
						idField = mId.getDeclaredField(userIdField);
					} catch (SecurityException e) {
					} catch (NoSuchFieldException e) {
					}
				}else {
					try {
						idField = mId.getDeclaredField(fieldName);
					} catch (SecurityException e) {
					} catch (NoSuchFieldException e) {
					}
					if(idField == null && fieldName.startsWith("m")) {
						try {
							idField = mId.getDeclaredField(getRemoveMName(fieldName));
						} catch (SecurityException e) {
							e.printStackTrace();
						} catch (NoSuchFieldException e) {
							e.printStackTrace();
						}
					}
				}
				if(idField != null) {
					try {
						int id = idField.getInt(null);
						field.setAccessible(true);
						View view = mActivity.findViewById(id);
						if(view == null) {
							throw new WireException("field \'"+fieldName+"\' not wired! Check your settings or layout xml id value!" );
						}
						field.set(mActivity, view);
					} catch (IllegalArgumentException e) {
						e.printStackTrace();
					} catch (IllegalAccessException e) {
						e.printStackTrace();
					}
				}else {
					throw new WireException("field \'"+fieldName+"\' not wired! Check your settings or layout xml id value!" );
				}
			}
		}
	}

	private static String getRemoveMName(String fieldName) {
		String name = fieldName.substring(2);
		StringBuilder result = new StringBuilder();
		char fl = fieldName.charAt(1);
		result.append(String.valueOf(fl).toLowerCase());
		result.append(name);
		System.out.println("Field: = "+result.toString());
		return result.toString();
	}
}
